`timescale 1ns / 1ps

module Wallace_tree_16 (
	input		[16:0]in,
	input		[13:0]cin,
	output	S,
	output	C,
	output	[13:0]cout
);
	wire [4:0]l1;
	wire [3:0]l2;
	wire [1:0]l3;
	wire [1:0]l4;
	wire l5,l6;
	//1st layer
	fulladder f1(in[3],in[2],in[1],l1[0],cout[0]);
	fulladder f2(in[6],in[5],in[4],l1[1],cout[1]);
	fulladder f3(in[9],in[8],in[7],l1[2],cout[2]);
	fulladder f4(in[12],in[11],in[10],l1[3],cout[3]);
	fulladder f5(in[15],in[14],in[13],l1[4],cout[4]);
	//2nd layer
	fulladder f6(l1[0],l1[1],l1[2],l2[0],cout[5]);
	fulladder f7(l1[3],l1[4],in[0],l2[1],cout[6]);
	fulladder f8(cin[1],cin[2],cin[0],l2[2],cout[7]);
	fulladder f9(cin[3],cin[4],in[16],l2[3],cout[8]);
	//3rd layer
	fulladder f10(l2[0],l2[1],l2[2],l3[0],cout[9]);
	fulladder f11(l2[3],cin[5],cin[6],l3[1],cout[10]);
	//4th layer
	fulladder f12(l3[0],l3[1],cin[7],l4[0],cout[11]);
	fulladder f13(cin[8],cin[9],cin[10],l4[1],cout[12]);
	//5th layer
	fulladder f14(l4[0],l4[1],cin[11],l5,cout[13]);
	//6th layer
	fulladder f15(l5,cin[12],cin[13],S,C);
endmodule

module fulladder (
	input a,
    input b,
    input cin,
    output s,
    output cout
);
	assign {cout,s}=a+b+cin;
endmodule